package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CategoryClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CategoryBasicDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.StringUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.service.IInteractionReplyService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-03-26
 */
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {

    private final UserClient userClient;
    private final CourseClient courseClient;
    private final SearchClient searchClient;
    private final CatalogueClient catalogueClient;
    private final CategoryCache categoryCache;
    private final IInteractionReplyService interactionReplyService;

    @Override
    public PageDTO<QuestionVO> getPage(QuestionPageQuery questionPageQuery) {
        // 1、参数校验，课程Id和小节Id不能同时为空
        Long courseId = questionPageQuery.getCourseId();
        Long sectionId = questionPageQuery.getSectionId();
        if(ObjectUtils.isEmpty(courseId) && ObjectUtils.isEmpty(sectionId)) {
            throw new BadRequestException("课程ID和小节ID不能同时为空");
        }
        // 构建分页查询条件
        Page<InteractionQuestion> pageResult = this.lambdaQuery()
                .select(InteractionQuestion.class, tableFieldInfo -> !tableFieldInfo.getColumn().equals("description"))
                .eq(questionPageQuery.getOnlyMine(), InteractionQuestion::getUserId, UserContext.getUser())
                .eq(ObjectUtils.isNotEmpty(questionPageQuery.getCourseId()), InteractionQuestion::getCourseId, questionPageQuery.getCourseId())
                .eq(ObjectUtils.isNotEmpty(questionPageQuery.getSectionId()), InteractionQuestion::getSectionId, questionPageQuery.getSectionId())
                .eq(InteractionQuestion::getHidden, false)
                .page(questionPageQuery.toMpPageDefaultSortByCreateTimeDesc());

        List<InteractionQuestion> records = pageResult.getRecords();

        List<QuestionVO> questionVOS = new ArrayList<>(records.size());
        if (ObjectUtils.isEmpty(records)) {
            return PageDTO.empty(pageResult);
        }

        // 根据最近一次回答id结合进行查询，最近一次回答信息，转成map
        Set<Long> userIds = new HashSet<>(records.size());
        Set<Long> replyIds = new HashSet<>(records.size());

        Map<Long, InteractionReply> replyMp = new HashMap<>(records.size());
        Map<Long, UserDTO> userMp = new HashMap<>(records.size());
        for (InteractionQuestion record : records) {
            if (!record.getAnonymity()) {
                userIds.add(record.getUserId());
            }
            replyIds.add(record.getLatestAnswerId());
        }

            
        List<InteractionReply> interactionReplies = interactionReplyService.listByIds(replyIds);
        for (InteractionReply reply : interactionReplies) {
            if (!reply.getAnonymity()) {
                userIds.add(reply.getUserId());
            }
            replyMp.put(reply.getId(), reply);
        }

        List<UserDTO> userDTOList = null;
        if (ObjectUtils.isNotEmpty(userIds)) {
             userDTOList = userClient.queryUserByIds(userIds);
        }

        if (ObjectUtils.isNotEmpty(userDTOList)) {
            userMp = userDTOList.stream().collect(Collectors.toMap(v->v.getId(), Function.identity()));
        }




        
        // 循环拼装
        for (InteractionQuestion record : records) {
            QuestionVO questionVO = BeanUtils.copyBean(record, QuestionVO.class);

            if (!record.getAnonymity()) {
                UserDTO userDTO = userMp.get(record.getUserId());
                if (ObjectUtils.isNotEmpty(userDTO)) {
                    questionVO.setUserIcon(userDTO.getIcon());
                    questionVO.setUserName(userDTO.getUsername());
                }
            }

            InteractionReply interactionReply = replyMp.get(record.getLatestAnswerId());
            if (ObjectUtils.isNotEmpty(interactionReply)) {
                questionVO.setLatestReplyContent(interactionReply.getContent());
                if (!interactionReply.getAnonymity()) {
                    UserDTO userDTO = userMp.get(interactionReply.getUserId());
                    if (ObjectUtils.isNotEmpty(userDTO)) {
                        questionVO.setLatestReplyUser(userDTO.getName());
                    }
                }
            }

            
            
            questionVOS.add(questionVO);
        }

        return PageDTO.of(pageResult, questionVOS);

    }

    @Override
    public PageDTO<QuestionAdminVO> getPage(QuestionAdminPageQuery questionAdminPageQuery) {

        List<Long> ids = null;
        if (ObjectUtils.isNotEmpty(questionAdminPageQuery.getCourseName())) {
            ids = searchClient.queryCoursesIdByName(questionAdminPageQuery.getCourseName());
            if (ObjectUtils.isEmpty(ids)) {
                return PageDTO.empty(0L, 0L);
            }
        }
        // 查询分页结果
        Page<InteractionQuestion> pageResult = this.lambdaQuery()
                .ge(ObjectUtils.isNotEmpty(questionAdminPageQuery.getBeginTime()), InteractionQuestion::getCreateTime, questionAdminPageQuery.getBeginTime())
                .le(ObjectUtils.isNotEmpty(questionAdminPageQuery.getEndTime()), InteractionQuestion::getCreateTime, questionAdminPageQuery.getEndTime())
                .eq(ObjectUtils.isNotEmpty(questionAdminPageQuery.getStatus()), InteractionQuestion::getStatus, questionAdminPageQuery.getStatus())
                .in(ObjectUtils.isNotEmpty(ids), InteractionQuestion::getCourseId, ids)
                .page(questionAdminPageQuery.toMpPageDefaultSortByCreateTimeDesc());

        // 取出其中的 records
        List<InteractionQuestion> records = pageResult.getRecords();
        if (ObjectUtils.isEmpty(records)) {
            return PageDTO.empty(pageResult);
        }

        // 拿到用户名称
        List<Long> idss = records.stream().map(v -> v.getUserId()).collect(Collectors.toList());
        List<UserDTO> userDTOS = userClient.queryUserByIds(idss);
        Map<Long, String> userMp = userDTOS.stream().collect(Collectors.toMap(v->v.getId(), v->v.getUsername()));

        // 拿到课程名称
        //List<Long> collect = records.stream().map(InteractionQuestion::getCourseId).collect(Collectors.toList());
        List<CourseSimpleInfoDTO> simpleInfoList = courseClient.getSimpleInfoList(ids);
        Map<Long, CourseSimpleInfoDTO> courseMp = simpleInfoList.stream().collect(Collectors.toMap(v->v.getId(), v->v));

        // 拿到章名称
        List<Long> chapterIds = records.stream().map(InteractionQuestion::getChapterId).collect(Collectors.toList());
        List<CataSimpleInfoDTO> chapterList = catalogueClient.batchQueryCatalogue(chapterIds);
        Map<Long, String> chapterMp = chapterList.stream().collect(Collectors.toMap(v->v.getId(), v->v.getName()));

        // 拿到节名称
        List<Long> sectionIds = records.stream().map(InteractionQuestion::getSectionId).collect(Collectors.toList());
        List<CataSimpleInfoDTO> sectionList = catalogueClient.batchQueryCatalogue(sectionIds);
        Map<Long, String> sectionMp = sectionList.stream().collect(Collectors.toMap(v->v.getId(), v->v.getName()));

        // 三级分类名称
        Map<Long, CategoryBasicDTO> categoryMp = categoryCache.getCategoryMap();


        List<QuestionAdminVO> recordss = new ArrayList<>();
        for (InteractionQuestion record : records) {
            QuestionAdminVO questionAdminVO = BeanUtils.copyBean(record, QuestionAdminVO.class);

            Long userId = record.getUserId();
            Long courseId = record.getCourseId();
            Long chapterId = record.getChapterId();
            Long sectionId = record.getSectionId();

            // 拿到提问者的昵称
            questionAdminVO.setUserName(userMp.get(userId));
            questionAdminVO.setChapterName(chapterMp.get(chapterId));
            questionAdminVO.setSectionName(sectionMp.get(sectionId));
            questionAdminVO.setCourseName(courseMp.get(courseId).getName());

            // 开始拼凑三级域名
            Long firstId = courseMp.get(courseId).getFirstCateId();
            Long secondId = courseMp.get(courseId).getSecondCateId();
            Long thirdId = courseMp.get(courseId).getThirdCateId();

            String one = ObjectUtils.isNotEmpty(categoryMp.get(firstId)) ? categoryMp.get(firstId).getName() : "";
            String two = ObjectUtils.isNotEmpty(categoryMp.get(secondId)) ? categoryMp.get(secondId).getName() : "";
            String three = ObjectUtils.isNotEmpty(categoryMp.get(thirdId)) ? categoryMp.get(thirdId).getName() : "";
            String threeName = one + "/" + two + "/" + three;
            questionAdminVO.setCategoryName(threeName);

            recordss.add(questionAdminVO);
        }


        return PageDTO.of(pageResult, recordss);
    }

    @Override
    public QuestionVO getQuestionVo(Long id) {
        // 空指针异常
        // 打日志
        // stream流
        // 加事务
        InteractionQuestion byId = this.getById(id);
        QuestionVO questionVo = BeanUtils.copyBean(byId, QuestionVO.class);

        UserDTO userDTO = userClient.queryUserById(questionVo.getUserId());
        if (!questionVo.getAnonymity() && ObjectUtils.isNotEmpty(userDTO)) {
            questionVo.setUserName(userDTO.getUsername());
            questionVo.setUserIcon(userDTO.getIcon());
            questionVo.setUserId(userDTO.getId());
        }

        InteractionReply byId1 = interactionReplyService.getById(byId.getLatestAnswerId());

        if (ObjectUtils.isNotEmpty(byId1)) {
            questionVo.setLatestReplyContent(byId1.getContent());
            // 第二次远程调用, 为了拿到回复者的昵称
            UserDTO userDTO1 = userClient.queryUserById(byId1.getUserId());
            // 设置最新的回答者昵称
            questionVo.setLatestReplyUser(userDTO1.getName());
        }

        return questionVo;

    }

    /**
     * 根据 id 拿到 QuestionAdminVO
     *
     * @param id
     * @return
     */
    @Override
    public QuestionAdminVO getQuestionAdminVo(Long id) {
        InteractionQuestion byId = this.getById(id);
        QuestionAdminVO questionAdminVo = BeanUtils.copyBean(byId, QuestionAdminVO.class);

        if (ObjectUtils.isNotEmpty(byId)) {
            UserDTO userDTO = userClient.queryUserById(byId.getUserId());
            questionAdminVo.setUserName(userDTO.getUsername());

            Long courseId = byId.getCourseId();
            CourseFullInfoDTO courseInfoById = courseClient.getCourseInfoById(byId.getCourseId(), false, false);
            if (ObjectUtils.isNotEmpty(courseInfoById)) {
                questionAdminVo.setCourseName(courseInfoById.getName());
            }
            List<CataSimpleInfoDTO> cataSimpleInfoDTOS = catalogueClient.batchQueryCatalogue(Arrays.asList(byId.getChapterId(), byId.getSectionId()));

            if (ObjectUtils.isNotEmpty(cataSimpleInfoDTOS)) {
                questionAdminVo.setChapterName(cataSimpleInfoDTOS.get(0).getName());
                questionAdminVo.setSectionName(cataSimpleInfoDTOS.get(1).getName());
            }

            Long firstId = courseInfoById.getFirstCateId();
            Long secondId = courseInfoById.getSecondCateId();
            Long thirdId = courseInfoById.getThirdCateId();

            Map<Long, CategoryBasicDTO> categoryMp = categoryCache.getCategoryMap();

            String one = ObjectUtils.isNotEmpty(categoryMp.get(firstId)) ? categoryMp.get(firstId).getName() : "";
            String two = ObjectUtils.isNotEmpty(categoryMp.get(secondId)) ? categoryMp.get(secondId).getName() : "";
            String three = ObjectUtils.isNotEmpty(categoryMp.get(thirdId)) ? categoryMp.get(thirdId).getName() : "";
            String threeName = one + "/" + two + "/" + three;
            questionAdminVo.setCategoryName(threeName);

            List<Long> teacherIds = courseInfoById.getTeacherIds();
            List<String> teacherNames = userClient.queryUserByIds(teacherIds).stream().map(v->v.getUsername()).collect(Collectors.toList());

            questionAdminVo.setTeacherName(StringUtils.join(",", teacherNames));
        }

        return questionAdminVo;
    }

    @Override
    public void hideAll(Long id) {
        this.lambdaUpdate()
                .eq(InteractionQuestion::getId, id)
                .set(InteractionQuestion::getHidden, true)
                .update();

        this.interactionReplyService.lambdaUpdate()
                .eq(InteractionReply::getQuestionId, id)
                .set(InteractionReply::getHidden, true)
                .update();
    }

    @Override
    public void displayAll(Long id) {
        this.lambdaUpdate()
                .eq(InteractionQuestion::getId, id)
                .set(InteractionQuestion::getHidden, false)
                .update();

        this.interactionReplyService.lambdaUpdate()
                .eq(InteractionReply::getQuestionId, id)
                .set(InteractionReply::getHidden, false)
                .update();
    }


}
